#include <string.h>
#include <stdio.h>
#include "thr.h"

/* 记录所有创建的线程实例 */
int nthrhnd = 0;
struct __thread_handle* thrhnd_array[256];

/**
  * @brief  设置线程属性
  * @Notes  只能放到线程函数无限大循环while(1){ ... } 前一行
  *         线程结束回收资源时必须使用 THREAD_Deconstruct 函数
  * @param  thrhnd, 线程实例句柄
  * @param  thread_name, 线程名称
  * @retval None.
  */
void THREAD_SetProperty_before_infinite_loop(struct __thread_handle* thrhnd, char* thread_name)
{
#ifdef OS_Linux
  /* 设置线程名称 */
  strcpy(thrhnd->tName, thread_name);
  prctl(PR_SET_NAME, thrhnd->tName);
  //fprintf(stderr, "Thread/> set thread name '%s' successfully.\n", thrhnd->tName);
#endif
  /* 允许其他线程在线取消当前线程 */
  pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
  /*异步取消当前线程， 本线程接到其他线程的取消信号后，立即退出*/
  pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
}

#if 0
void thr_property(struct __thread_handle* thrhnd, char* thread_name)
{
  /* 运行函数
   * 函数传入参数: void*
   * 函数返回值:  void*
   */
  ((void* (*)(void*))thrhnd->tFunction)(NULL);
}
#endif

/**
  * @brief  线程实例初始化
  * @Notes  None.
  * @param  thrhnd, 线程实例
  * @param  function, 线程函数
  * @param  parameter, 外部传递给线程的参数
  * @retval None.
  */
int THREAD_Construct(struct __thread_handle* thrhnd, 
                      void* (*function)(void* para), void* parameter)
{
  thrhnd->tFunction = function;
  thrhnd->tPara = parameter;
  if(pthread_create(&thrhnd->tID, NULL, thrhnd->tFunction, thrhnd->tPara) != 0){
    thrhnd->tFlag = THREAD_FLAG_NONE;
        perror("Thread/> {ERROR} pthread_create");
        return -1;
    }else{
      thrhnd->tFlag = THREAD_FLAG_RUNNING;
      thrhnd_array[nthrhnd] = thrhnd;
      nthrhnd++;
      //记录创建线程时间点
      time(&(thrhnd->uptime));
      //printf("Thread/> {INFO} Create thread successfully.\n"); 
      return 0;
    }
}


/**
  * @brief  线程实例资源回收
  * @Notes  None.
  * @param  thrhnd, 线程实例
  * @retval None.
  */
void THREAD_Deconstruct(struct __thread_handle* thrhnd)
{
  void *ret=NULL; 
  /* 取消线程 */
  pthread_cancel(thrhnd->tID); 
  /* 阻塞等待线程结束并释放资源完成. */
  pthread_join(thrhnd->tID, &ret);  
  thrhnd->tFlag = THREAD_FLAG_NONE;
  thrhnd->tPara = NULL;
  thrhnd->tFunction = NULL;
#ifdef OS_Linux
  fprintf(stderr, "Thread/> {INFO} %s closed.\n", thrhnd->tName);
#endif
}

struct __thread_handle* thr_get_handle(pthread_t thr_id)
{
  int i;
  for(i = 0; i < nthrhnd; i++)
  {
    if(thrhnd_array[i]->tID == thr_id)
    {
      return thrhnd_array[i];
    }
  }
  return NULL;
}

char* thr_running_time(struct __thread_handle* thrhnd)
{
    time_t now;
    time(&now);
    time_t running_sec = now - thrhnd->uptime;
    int day, hour, minute, second;
    day = running_sec/(3600*24);
    running_sec = running_sec%(3600*24);
    hour = running_sec/3600;
    running_sec = running_sec%3600;
    minute = running_sec/60;
    second = running_sec%60;

    int l = sprintf(thrhnd->runtime, "[%d]day [%d]hour [%d]minute [%d]second", 
                                    day, hour, minute, second);
    return thrhnd->runtime;
}